package io.tim.timongodb.util;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentFactory;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 负责实例、数据的 XML 操作
 *
 * @author zhangnan
 * @date 2017年4月24日
 *
 */
public class InstanceXMLBuilder {

	private static final Logger LOGGER = LoggerFactory.getLogger(ClassUtil.class);

	/**
	 * 新建实例 xml 文件
	 * @param instanceName
	 * @param instancePath
	 * @param instanceFileName
	 */
	public static void NewInstanceXML(String instanceName, String instancePath, String instanceFileName) {
		// 创建根节点 并设置它的属性，数据库实例名和包含的数据库数量，新建为0;
		Document doc = DocumentFactory.getInstance().createDocument();
		Element root = DocumentHelper.createElement("databases");
		root.addAttribute("name", instanceName);
		root.addAttribute("count", "0");
		doc.setRootElement(root);

		// 输出 instance xml 文件，并使用缩进格式
		OutputFormat format = new OutputFormat("	", true);
		format.setIndent("	");

		FileOutputStream os = null;
		XMLWriter writer = null;
		try {
			os = new FileOutputStream(instancePath + instanceFileName);
			writer = new XMLWriter(os, format);
			writer.write(doc);
		} catch (IOException e) {
			LOGGER.error("fail to create instance xml file!");
			throw new RuntimeException(e);
		} finally {
			if (os != null) {
				try {
					os.close();
				} catch (IOException e) {
					LOGGER.error("fail to close instance xml file outputstream!");
					throw new RuntimeException(e);
				}
			}
		}

	}
	
	/**
	 * 将数据库添加到实例 xml 文件中
	 * @param instPath
	 * @param instFileName
	 * @param dbName
	 * @param dbFile
	 */
	public static void AddDatabaseToInstanceXML(String instPath, String instFileName, String dbName, String dbFile) {
		SAXReader reader = new SAXReader();

		FileInputStream instanceFileIS = null;
		try {
			instanceFileIS = new FileInputStream(instPath + instFileName);
		} catch (FileNotFoundException e1) {
			e1.printStackTrace();
		}

		Document document = null;
		try {
			document = reader.read(instanceFileIS);
		} catch (DocumentException e1) {
			e1.printStackTrace();
		}
		Element root = document.getRootElement();
		List<Element> databaseList = root.elements();
		Boolean dbExist = false;
		if (databaseList.size() > 0) {
			for (Element e : databaseList) {
				String name = e.attributeValue("dbName");
				if (name.equals(dbName)) {
					dbExist = true;
					break;
				}
			}
		}
		if (dbExist == true) {
			LOGGER.error("the database " + dbName + " has already existed in the instance XML!");
			LOGGER.error("fail to add database " + dbName + " into the instance XML!");
		} else {
			Attribute count = root.attribute("count");
			String dataBaseCount = root.attributeValue("count");
			count.setValue(Integer.toString((Integer.parseInt(dataBaseCount) + 1)));

			Element dataBaseElement = root.addElement("database");
			dataBaseElement.addAttribute("dbName", dbName);
			dataBaseElement.addAttribute("dbFile", dbFile);

			// 使 xml文件 缩进效果
			OutputFormat format = OutputFormat.createPrettyPrint();
			// 设置编码
			format.setEncoding("UTF-8");

			FileOutputStream os = null;
			XMLWriter writer = null;
			try {
				os = new FileOutputStream(instPath + instFileName);
				writer = new XMLWriter(os, format);
				writer.write(document);
			} catch (IOException e) {
				LOGGER.error("fail to write instance xml file!");
				throw new RuntimeException(e);
			} finally {
				if (writer != null) {
					try {
						writer.flush();
						writer.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
				if (os != null) {
					try {
						os.close();
					} catch (IOException e) {
						LOGGER.error("fail to close instance xml file outputstream!");
						throw new RuntimeException(e);
					}
				}
			}
		}

	}

	/**
	 * 新建数据库的 xml 文件，以后用于向里面添加表和表数据
	 * @param instName
	 * @param dbName
	 * @param dbFileName
	 */
	public static void NewDataBaseXML(String instName, String dbName, String dbFileName) {
		// 创建根节点 并设置它的属性 ;
		// 因为是新建 Instance，所以计数为 0
		Document doc = DocumentFactory.getInstance().createDocument();
		Element root = DocumentHelper.createElement("database");
		root.addAttribute("name", dbName);
		root.addAttribute("instance", instName);
		// 将根节点添加到文档中；
		doc.setRootElement(root);

		// 输出 instance xml 文件；
		// 使 xml文件 缩进效果
		OutputFormat format = new OutputFormat("	", true);
		format.setIndent("	");

		FileOutputStream os = null;
		XMLWriter writer = null;
		try {
			os = new FileOutputStream(dbFileName);
			writer = new XMLWriter(os, format);
			writer.write(doc);
		} catch (IOException e) {
			LOGGER.error("fail to create instance xml file!");
			throw new RuntimeException(e);
		} finally {
			if (os != null) {
				try {
					os.close();
				} catch (IOException e) {
					LOGGER.error("fail to close instance xml file outputstream!");
					throw new RuntimeException(e);
				}
			}
		}

	}

	/**
	 * 显示 xml 文档中的子节点
	 * @param XMLPath
	 */
	public static void lisXMLNodes(String XMLPath) {
		SAXReader reader = new SAXReader();

		FileInputStream instanceFileIS = null;
		try {
			instanceFileIS = new FileInputStream(XMLPath);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		Document document = null;
		try {
			document = reader.read(instanceFileIS);
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		Element root = document.getRootElement();
		listElementNodes(root);
	}

	/**
	 * 遍历当前节点元素下面的所有(元素的)子节点
	 * 
	 * @param node
	 */
	public static void listElementNodes(Element node) {
		System.out.println("当前节点的名称：：" + node.getName());
		// 获取当前节点的所有属性节点
		List<Attribute> list = node.attributes();
		// 遍历属性节点
		for (Attribute attr : list) {
			System.out.println(attr.getText() + "-----" + attr.getName() + "---" + attr.getValue());
		}

		if (!(node.getTextTrim().equals(""))) {
			System.out.println("文本内容：" + node.getText());
		}

		// 当前节点下面子节点迭代器
		Iterator<Element> it = node.elementIterator();
		// 遍历
		while (it.hasNext()) {
			// 获取某个子节点对象
			Element e = it.next();
			// 对子节点进行遍历
			listElementNodes(e);
		}
	}

	/**
	 * 通过实例 xml 文件和数据库名称返回数据库文件名
	 */
	public static String getDBFileName(String instFilePath, String dbName) {
		System.out.println("instance file path: " + instFilePath);
		FileInputStream instanceFileIS = null;
		try {
			instanceFileIS = new FileInputStream(instFilePath);
		} catch (FileNotFoundException e1) {
			e1.printStackTrace();
		}
		SAXReader reader = new SAXReader();
		Document document = null;
		try {
			document = reader.read(instanceFileIS);
		} catch (DocumentException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		Element root = document.getRootElement();
		@SuppressWarnings("unchecked")
		List<Element> elementList = root.elements();

		String dbFileName = null;
		if (elementList.size() > 0) {
			for (Element e : elementList) {
				System.out.println("element name is : " + e.getName());
				String name = e.attributeValue("dbName");
				if (name.equals(dbName)) {
					dbFileName = e.attributeValue("dbFile");
					break;
				}
			}
		}
		return dbFileName;
	}

	/**
	 * 向数据库 xml 文件中添加表节点
	 * @param dbFilePath
	 * @param tableName
	 */
	public static void addTableToDBXML(String dbFilePath, String tableName) {

		// 插入数据库-创建表
		FileInputStream dbFileIS = null;
		try {
			dbFileIS = new FileInputStream(dbFilePath);
		} catch (FileNotFoundException e1) {
			e1.printStackTrace();
		}
		SAXReader reader = new SAXReader();
		Document document = null;
		try {
			document = reader.read(dbFileIS);
		} catch (DocumentException e1) {
			e1.printStackTrace();
		}
		Element databaseRoot = document.getRootElement();
		Element tableEle = databaseRoot.addElement("table");
		tableEle.addAttribute("name", tableName);
		// 使 xml文件 缩进效果
		OutputFormat format = OutputFormat.createPrettyPrint();
		// 设置编码
		format.setEncoding("UTF-8");

		FileOutputStream os = null;
		XMLWriter writer = null;
		try {
			os = new FileOutputStream(dbFilePath);
			writer = new XMLWriter(os, format);
			writer.write(document);
		} catch (IOException e) {
			LOGGER.error("fail to write instance xml file!");
			throw new RuntimeException(e);
		} finally {
			if (writer != null) {
				try {
					writer.flush();
					writer.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (os != null) {
				try {
					os.close();
				} catch (IOException e) {
					LOGGER.error("fail to close instance xml file outputstream!");
					throw new RuntimeException(e);
				}
			}
		}

	}
}
